home *** CD-ROM | disk | FTP | other *** search
- /*===========================================================================
- cb.c - C program indenter
-
- Revision History:
- 08/08/87 Robert B. Sledge (Compuserve 76515,2620):
- Obtained cb.c source from C User's Group.
- Added extensive comments (there were none).
- Changed operation to rename original file to .BAK and
- write output to file of original name.
- Added support for variable indent_spaces.
- Added switches -s, -b, and -l to command line.
- Corrected a number of processing bugs.
- Compiled with Microsoft C 4.0 compiler.
- Added switches to compile under VAX/VMS.
-
- 10/30/83 John W. Kindschi Jr.: Modified for Lattice C Ver 1.01
-
- ??/??/?? William C. Colley, III: Swiped from CPIG'S UNIX system and
- modified to run under BDS C.
-
- Usage: cb [-blis] inputfile [inputfile...]
-
- Switches:
-
- -b Braces indent at level of outside code.
- (Default = indent at level of inside code.)
- -l Indentation starts at level 1.
- (Default = indentation starts at level 0.)
- -inn Set number of spaces per indentation level to nn.
- (Default = indentation set to 3 spaces per level.)
- -s Output written to standard output.
- (Default = output to file, rename old .BAK.)
-
- Where inputfile is the file to be pretty printed (the filename may
- contain wildcard characters). Under MS-DOS the original file is renamed to
- .BAK unless the -s switch is used. Under VAX/VMS a new version of the file
- is created.
- ===========================================================================*/
-
-
- #include <stdio.h>
- #ifndef vms
- #include <errno.h> /* for the MSC rename() function */
- #endif
-
- #define TEMPNAME "cbtemp.czz" /* temp output file name */
- #define SORTOF 2
- #define YES 1
- #define NO 0
-
- #define BRACES_OUTSIDE 0 /* braces at outside block level */
- #define BRACES_INSIDE 1 /* braces at inside block level */
-
- #define START0LEVEL 0 /* indenting starts at level 0 */
- #define START1LEVEL 1 /* indenting starts at level 1 */
-
- #define SUCCESS 0 /* return codes for renambak() */
- #define FAILURE1 -1
- #define FAILURE2 -2
-
- #define MAXBRACE 20 /* max nested brace level allowed */
- #define MAXIF 10 /* max nested 'if' level allowed */
- #define MAXLEVEL 10 /* max number of braced blocks preceeded by
- * non-braced block statements */
-
- int swflg = NO; /* processing 'switch' flag */
- int sswflg[MAXBRACE]; /* saved 'swflg's */
-
- int aflg[MAXLEVEL]; /* YES/NO flag (has to do with braces???) */
- int saflg[MAXBRACE][MAXIF]; /* saved aflg[] */
- int nblk[MAXLEVEL]; /* non-braced blocks at current 'level' */
- int snblk[MAXBRACE][MAXIF]; /* saved nblks[] */
- int brclev = 0; /* brace {} level: increments on '{'
- * and decrements on '}' */
- int sbrclev[MAXLEVEL]; /* saved 'brclev's */
- int iflev = 0; /* 'if' level */
- int siflev[MAXBRACE]; /* saved 'iflev's */
- int ifflg = -1; /* processing 'if' flag */
- int sifflg[MAXBRACE]; /* saved 'ifflg's */
- int tabs = 0; /* current level of indentation */
- int stabs[MAXBRACE][MAXIF]; /* saved 'tabs' */
- int level = 0; /* brace level after non-braced block stmt */
- int addflg = NO; /* add-extra-indent flag */
- int elseflg = NO; /* processing 'else' flag */
- int qflg = NO; /* question mark flag */
- int solflg = YES; /* start-of-line flag */
- int stdoutflg = NO; /* flag to use stdout for output */
- int tabsflg = START0LEVEL; /* indenting starts at level 0 */
- int paren = 0; /* 'parenthesis' level */
- int peek = -1; /* peekahead character */
- int j = 0; /* char index for output buffer */
- int nindent = 3; /* number of spaces per indent level */
- int braces = BRACES_INSIDE; /* braces indent at inside block level */
- FILE *inpfile, *outfile; /* input and output file pointers */
-
- static char string[200]; /* output string buffer */
-
- char *wif[2] = { "if", NULL };
- char *welse[2] = { "else", NULL };
- char *wfor[2] = { "for", NULL };
- char *wcase[3] = { "case", "default", NULL };
- char *wswitch[2]= { "switch", NULL };
- char lchar; /* last non-whitespace && non-comma char written to output */
- char pchar; /* previous non-whitespace char from input stream */
- int lastchar; /* last character received */
- int c; /* character buffer */
- char cc; /* character buffer */
-
-
- main( argc, argv)
- int argc;
- char **argv;
- {
- void cb(); /* main processing function */
- char *findfile(); /* vms wildcard processing routine */
- int n; /* loop index variable */
- char *arg; /* ptr to command line character */
- char *ptr; /* ptr to filename string */
-
- /* show the correct usage of this utility */
- if (argc <= 1)
- {
- fprintf(stderr, "V2.1 Usage: cb [-blis] inputfile [inputfile...]\n");
- fprintf(stderr, " Switches:\n\n");
- fprintf(stderr, " -b Braces indent at level of outside code.\n");
- fprintf(stderr, " (Default = indent at level of inside code.)\n");
- fprintf(stderr, " -l Indentation starts at level 1.\n");
- fprintf(stderr, " (Default = indentation starts at level 0.)\n");
- fprintf(stderr, " -inn Set number of spaces per indentation level to nn.\n");
- fprintf(stderr, " (Default = indentation set to 3 spaces per level.)\n");
- fprintf(stderr, " -s Output written to standard output.\n");
- #ifdef vms
- fprintf(stderr, " (Default = Create a new version of the file.)\n");
- #else
- fprintf(stderr, " (Default = output to file, rename old .BAK.)\n");
- #endif
- return;
- }
-
- /* process command line tokens */
- while( --argc > 0)
- {
- /* process a command line switch */
- arg = *++argv;
- if ( *arg == '-')
- {
- /* handle multiple switches behind a single '-' */
- while( *++arg != '\0')
- switch (*arg)
- {
- default:
- fprintf(stderr, "Unknown Switch (-%c)... Ignored!!\n", *arg);
- break;
-
- case 'b':
- case 'B':
- braces = BRACES_OUTSIDE; /* braces at outside code level */
- break;
-
- case 'i':
- case 'I':
- if ((n=atoi(++arg)) > 0)
- nindent = n; /* set spaces per indent */
- /* skip over the digits in the number */
- while (*(arg+1) >= '0' && *(arg+1) <= '9')
- arg++;
- break;
-
- case 'l':
- case 'L':
- tabsflg = START1LEVEL; /* indentation starts at level 1 */
- break;
-
- case 's':
- case 'S':
- stdoutflg = YES; /* output goes to standard out */
- break;
- } /* end switch() */
- }
- /* not a command line switch: process as a filename */
- else
- {
- #ifdef vms
- /* findfile() returns ptr to matching (possibly wildcard) file specs.
- * this is where we handle wildcards for vms */
- while ( (ptr=findfile(arg)) != NULL)
- cb( ptr); /* process the filename ptd to by 'ptr' */
- #else
- cb( arg); /* process the filename ptd to by 'arg' */
- #endif
- }
-
- } /* end while() to process command line tokens */
-
- } /*----------------------------- main() --------------------------------*/
-
-
- /*-----------------------------------------------------------------------*
- * cb() - beautify the specified file
- *
- * Synopsis:
- * cb( filename)
- * char *filename; ptr to name of file to process
- *
- * Returns: void
- *-----------------------------------------------------------------------*/
-
- void cb( filename)
- char *filename; /* ptr to name of file to process */
- {
- int ct;
- int i,n; /* temp variables */
-
- /* open the input file */
- if ( (inpfile = fopen(filename,"r")) == NULL)
- {
- fprintf(stderr, "\nFile (%s) not found.\n\n", filename);
- return;
- }
-
- /* open the output stream */
- if (stdoutflg == NO)
- {
- #ifdef vms
- /* remove explicit version number so file defaults to next higher version */
- for( n = strlen(filename); n >= 0; n--)
- if (filename[n] == ';')
- filename[n] = '\0';
- if ((outfile = fopen(filename,"w")) == NULL)
- {
- fprintf( stderr, "Couldn't create output file (%s).\n", filename);
- return;
- }
- #else /* non-vms */
- if ((outfile = fopen(TEMPNAME,"w")) == NULL)
- {
- fprintf( stderr, "Couldn't create output file (%s).\n", filename);
- return;
- }
- #endif
- }
- /* open the output stream to stdout */
- else
- outfile = stdout;
-
- /* initialize parameters */
- cbinit();
-
- /* process the characters from the input file and send to output stream */
- while ( (c=getchr()) != EOF)
- {
- switch(c) /* switch on input character */
- {
- /* not a special character: just pack it into output string */
- default:
- string[j++] = c;
- if (c != ',')
- lchar = c; /* remember last character */
- break;
-
- /* handle a whitespace character */
- case ' ':
- case '\t':
- if (lookup(welse) == YES) /* processing an 'else' */
- {
- elseflg = SORTOF; /* remember the 'else' statement */
- gotelse(); /* adjust for the 'else' */
- /* not start-of-line or characters in output buffer */
- if( solflg == NO || j > 0)
- string[j++] = c; /* copy whitespace to output buf */
- putb(); /* write output buffer */
- solflg = NO; /* not start-of-line */
- break; /* loop back around */
- }
- /* not start-of-line or chars in buffer */
- if (solflg == NO || j > 0)
- string[j++] = c; /* copy whitespace to output buf */
- break; /* loop back around */
-
- /* handle a newline character */
- case '\n':
- /* Check for processing an 'else' statement.
- * Elseflg may have been set previously by the ' ' or '\t' special
- * character case statement, in which case gotelse() has already
- * been called and we don't want to call it again here. Note that
- * we won't detect the else here in that case since putb() has
- * been called and flushed the 'else' to the output stream. In order
- * to help us here we set elseflg=SORTOF back there so we can go ahead
- * and appropriately handle the 'else' here.
- */
- if (elseflg != SORTOF && (elseflg=lookup(welse)) == YES)
- gotelse(); /* adjust for this 'else' stmt */
- putb(); /* write output buffer */
- fprintf( outfile, "\n"); /* write newline to output stream */
- solflg = YES; /* start-of-line is true */
- /* we are processing an 'else' */
- if (elseflg == YES || elseflg == SORTOF)
- {
- nblk[level]++; /* increment non-braced block count */
- tabs++; /* stuff after 'else' is indented */
- elseflg = NO; /* reset the flag */
- }
- /* somewhere inside parenthesis: add an extra temp indent */
- else if( paren > 0)
- addflg = YES;
- break; /* loop back around */
-
- /* handle a left brace */
- case '{':
- if (lookup(welse) == YES) /* processing an 'else' */
- gotelse();
- siflev[brclev] = iflev; /* save 'if' level */
- sifflg[brclev] = ifflg; /* save 'if' flag */
- iflev = 0; /* current 0 at new brace level */
- ifflg = NO; /* no 'if's yet at new brace level */
- sswflg[brclev] = swflg; /* save 'switch' flag */
- if (++brclev > MAXBRACE) /* increment brace level */
- {
- fprintf(stderr,"Too many nested braces in (%s), aborting!!\n",
- filename);
- goto END;
- }
- /* start-of-line and non-braced block statements above us */
- if (solflg == YES && nblk[level] > 0)
- {
- nblk[level]--; /* decrement since we now have a brace */
- tabs--; /* and it will indent things for us */
- }
- string[j++] = c; /* store '{' in output buffer */
- /* braces at inside block level (never for switch stmt) */
- if (swflg == NO && braces == BRACES_INSIDE)
- tabs++; /* indent right one level */
- putb(); /* write buffer to output stream */
- getnl(); /* get remaining whitespace & comments */
- putb(); /* write buffer to output stream */
- fprintf( outfile, "\n"); /* write newline to output stream */
- solflg = YES; /* start-of-line is true */
- /* braces at outside block level (always for switch stmt) */
- if (swflg == YES || braces == BRACES_OUTSIDE)
- tabs++; /* indent right one level */
- swflg = NO; /* no 'switch's yet at this level */
- /* some non-braced block statements above us at this 'level' */
- if (nblk[level] > 0)
- {
- aflg[level] = YES; /* set flag true */
- /* start new brace level following some non-braced block stmts */
- if (++level > MAXLEVEL)
- {
- fprintf(stderr,"Too many nested braces in (%s), aborting!!\n",
- filename);
- goto END;
- }
- sbrclev[level] = brclev; /* save the brace level */
- }
- break; /* loop back around */
-
- /* handle a right brace */
- case '}':
- brclev--; /* decrement the brace level */
- if ((iflev = siflev[brclev]-1) < 0)
- iflev = 0;
- ifflg = sifflg[brclev]; /* restore 'if' flag at level */
- swflg = sswflg[brclev]; /* restore 'switch' flag */
- putb(); /* write output buffer */
- /* braces at outside block level (always for switch stmt) */
- if (swflg == YES || braces == BRACES_OUTSIDE)
- tabs--; /* indent left one level */
- ptabs(); /* output leading indentation */
- /* braces at inside block level (never for switch stmt) */
- if (swflg == NO && braces == BRACES_INSIDE)
- tabs--; /* indent left one level */
- swflg = sswflg[brclev] = NO; /* no 'switch' stmt at this point */
- /* peek at next character, it is a semicolon ';' */
- if ((peek = getchr()) == ';')
- {
- fprintf(outfile, "%c;", c); /* output the "};" to buffer */
- peek = -1; /* forget the ';' */
- }
- /* next character is not a semicolon ';' */
- else
- fprintf( outfile, "%c", c); /* output the '}' to buffer */
- getnl(); /* get remaining whitespace & comments */
- putb(); /* write output buffer */
- fprintf( outfile, "\n"); /* write newline to output stream */
- solflg = YES; /* start-of-line is true */
- /* conditions are right to decrement non-blocked brace level */
- if (brclev < sbrclev[level])
- if (level > 0)
- level--; /* decrement non-blocked brace level */
- /* leaving a braced block preceeded by non-braced block stmts */
- /* adjust things accordingly */
- if (aflg[level] > 0)
- {
- tabs -= nblk[level]; /* indent left appropriate number */
- nblk[level] = 0; /* no non-braced blocks at 'level' now */
- aflg[level] = NO; /* reset the aflg[] flag */
- }
- break; /* loop back around */
-
- /* handle a single quote or double quote */
- case '"':
- case '\'':
- string[j++] = c; /* copy quote to output buffer */
- /* copy characters within quotes to output buffer */
- while ( (cc=getchr()) != c)
- {
- string[j++] = cc; /* copy char to output buffer */
- if( cc == '\\') /* copy an escaped character */
- string[j++] = getchr(); /* straight into output buffer */
- if (cc == '\n') /* we have a newline */
- {
- putb(); /* write output buffer */
- solflg = YES; /* start-of-line is true */
- }
- }
- string[j++] = cc; /* copy last char to output buffer */
- /* get remaining whitespace & comments: we hit a newline */
- if (getnl() == YES)
- {
- lchar = cc; /* remember last character */
- peek = '\n'; /* remember the newline */
- }
- break; /* loop back around */
-
- /* handle a semicolon */
- case ';':
- string[j++] = c;
- putb();
- /* leaving one or more non-braced block statements */
- if (nblk[level] > 0 && aflg[level] == NO)
- {
- tabs -= nblk[level]; /* indent left an appropriate amount */
- nblk[level] = 0; /* no non-braced blocks at 'level' now */
- }
- getnl(); /* get remaining whitespace & comments */
- putb(); /* write the output buffer */
- fprintf( outfile, "\n"); /* write a newline to output stream */
- solflg = YES; /* start-of-line is true */
- /* we are in one or more nested 'if' statements */
- if (iflev > 0)
- /* we are currently processing an 'if' statement */
- if (ifflg == YES)
- {
- iflev--; /* decrement 'if' level */
- ifflg = NO; /* and reset the 'if' flag */
- }
- /* not currently processing an 'if' statement */
- else
- iflev = 0; /* not in nested 'if' stmts any more */
- break;
-
- /* handle an escaped character; copy both to output string */
- case '\\':
- string[j++] = c; /* copy the '\' */
- string[j++] = getchr(); /* copy the character */
- break;
-
- /* handle a question mark; it may be a conditional operator (?:) */
- case '?':
- qflg = YES; /* remember the '?' */
- string[j++] = c; /* copy to output string */
- break;
-
- /* handle a colon */
- case ':':
- string[j++] = c; /* copy to output string */
- /* we are processing a conditional operator (?:) */
- if (qflg == YES)
- { /* no further processing needed */
- qflg = NO; /* just cancel the flag */
- break; /* and loop back around */
- }
- /* processing 'case' or 'default' */
- if (lookup(wcase) == YES)
- {
- tabs--; /* indent left */
- putb(); /* write the "case:" or "default:" */
- tabs++; /* indent right */
- }
- /* not conditional operator (?:) or case: or default: */
- else
- {
- solflg = NO; /* start-of-line is false */
- putb(); /* write the output buffer */
- }
- /* if next character is a semicolon */
- if ((peek = getchr()) == ';')
- {
- fprintf( outfile, ";"); /* then output the ';' */
- peek = -1; /* don't remember the peek */
- }
- getnl(); /* get remaining whitespace and comments */
- putb(); /* write the output buffer */
- fprintf( outfile, "\n"); /* write a newline to output stream */
- solflg = YES; /* start-of-line is true */
- break; /* loop back around */
-
- /* handle a slash */
- case '/':
- string[j++] = c; /* copy to output buffer */
- if ( (peek=getchr()) != '*') /* next char is not a '*' */
- break; /* loop back around */
- string[j++] = peek; /* copy '*' to output buffer */
- peek = -1; /* forget the peek */
- comment(); /* handle rest of the comment */
- break; /* loop back around */
-
- /* handle a left parenthesis */
- case '(':
- string[j++] = c; /* copy '(' to the output buffer */
- paren++; /* increment paren level */
- /* processing 'for' statement */
- if (lookup(wfor) == YES)
- {
- /* gobble till we process a semicolon */
- while( (c=cgets()) != ';')
- ;
- ct = 0; /* no nesting yet */
- cont:
- /* gobble till we process a right paren */
- while ( (c=cgets()) != ')')
- {
- if (c == '(') /* we hit a left paren */
- ct++; /* increment nesting level */
- }
- /* we are still nested: keep gobbling */
- if (ct != 0)
- {
- ct--; /* decrease nesting level */
- goto cont; /* and continue gobbling till */
- } /* we find the right paren */
-
- paren--; /* decrement paren level */
- putb(); /* put the output line out */
-
- /* output whitespace and comments: handle multi-line 'for' */
- if (getnl() == YES) /* we got to a newline */
- {
- peek = '\n'; /* remember the newlne */
- nblk[level]++; /* increment non-braced block level */
- tabs++; /* indent right */
- aflg[level] = NO; /* reset the flag */
- }
- break; /* loop back around */
- } /* end 'for' processing */
-
- /* processing an 'if' statement */
- if (lookup(wif) == YES)
- {
- putb(); /* write output buffer */
- stabs[brclev][iflev] = tabs; /* save current state */
- snblk[brclev][iflev] = nblk[level];
- saflg[brclev][iflev] = aflg[level];
- if (++iflev > MAXIF) /* increment the 'if' level */
- {
- fprintf(stderr,"Too many nested 'if's in (%s), aborting!!\n",
- filename);
- goto END;
- }
- ifflg = YES; /* show that we are doing an 'if' stmt */
- } /* end 'if' processing */
-
- /* processing a 'switch' statement: set the flag */
- if (lookup(wswitch) == YES)
- swflg = YES; /* show that we're in 'switch' stmt */
- break; /* loop back around */
-
- /* handle a right parenthesis */
- case ')':
- paren--; /* decrement paren level */
- string[j++] = c; /* copy ')' to output buffer */
- putb(); /* write output buffer */
- /* get remaining whitespace and comments: we hit a newline */
- if (getnl() == YES)
- {
- peek = '\n'; /* remember the newline we hit */
- if (paren != 0) /* we are inside parens */
- addflg = YES; /* add-extra-indent is true */
- /* This is the where block statements that are terminated
- * by a right parenthesis receive their indentation. */
- else if (tabs > 0) /* we are indented */
- {
- nblk[level]++; /* increment non-braced block level */
- tabs++; /* indent right one level */
- aflg[level] = NO; /* reset the flag */
- /* If processing an 'else if(...)' (i.e. elseflg == SORTOF)
- * we don't want to indent again later so turn elseflg OFF.
- */
- if (elseflg == SORTOF)
- elseflg = NO;
- }
- }
- break; /* loop back around */
-
- /* handle a '#' character (preprocessor directive) */
- case '#':
- string[j++] = c; /* copy to output buffer */
- while ( (cc=getchr()) != '\n') /* copy up to newline */
- string[j++] = cc;
- string[j++] = cc; /* copy the newline to buffer */
- solflg = NO; /* start-of-line is false */
- putb(); /* write output buffer */
- solflg = YES; /* start-of-line is true */
- break; /* loop back around */
-
- } /* switch(c) */
-
- } /* while ( (c = getchar()) != EOF) */
-
- END:
- fclose( inpfile); /* close the input file */
-
- #ifdef vms
-
- if (stdoutflg == NO)
- fclose( outfile); /* close the output file */
-
- #else /* non-vms */
-
- /* MS-DOS: rename the original file to .BAK and rename new file */
- if (stdoutflg == NO)
- {
- fclose( outfile); /* close the output file */
- if ( renambak(filename) != SUCCESS)
- {
- fprintf( stderr, "Cannot rename (%s) to .BAK; Output = (%s)\n",
- filename, TEMPNAME);
- exit();
- }
- if (rename(TEMPNAME,filename) != SUCCESS)
- {
- fprintf( stderr, "Cannot rename temporary file; Output = (%s)\n",
- TEMPNAME);
- exit();
- }
- }
-
- #endif /* vms */
-
- } /*---------------------------- cb() ------------------------------*/
-
-
- /* cbinit() - initialize the beautifier variables
- *
- */
- cbinit()
- {
- register i, j;
-
- for (i = 0; i < MAXLEVEL; i++)
- {
- aflg[i] = 0; /* YES/NO flag (has to do with braces) */
- nblk[i] = 0; /* non-braced blocks at current 'level' */
- sbrclev[i] = 0; /* saved 'brclev's */
- }
-
- for (i = 0; i < MAXBRACE; i++)
- {
- sifflg[i] = 0; /* saved 'ifflg's */
- siflev[i] = 0; /* saved 'iflev's */
- sswflg[i] = 0; /* saved 'swflg's */
- for (j = 0; j < MAXIF; j++)
- {
- saflg[i][j] = 0; /* saved aflg[] */
- snblk[i][j] = 0; /* saved nblks[] */
- stabs[i][j] = 0; /* saved 'tabs' */
- }
- }
-
- brclev = 0; /* brace {} level: increments on '{'
- * and decrements on '}' */
- iflev = 0; /* 'if' level */
- ifflg = -1; /* processing 'if' flag */
- tabs = 0; /* current level of indentation */
- level = 0; /* brace level after non-braced block stmt */
- addflg = NO; /* add-extra-indent flag */
- elseflg = NO; /* processing 'else' flag */
- qflg = NO; /* question mark flag */
- solflg = YES; /* start-of-line flag */
- swflg = NO; /* processing 'switch' flag */
- paren = 0; /* 'parenthesis' level */
- peek = -1; /* peekahead character */
- j = 0; /* char index for output buffer */
-
- } /*---------------------------- cbinit() ---------------------------*/
-
-
- /* ptabs() - put out leading white space for proper indentation
- *
- * Returns: nothing
- */
- ptabs()
- {
- register i;
-
- /* don't output any leading whitespace unless we are at start-of-line */
- if (solflg == NO)
- return;
-
- /* if indenting starts at the left column */
- if (tabsflg == START0LEVEL)
- i = (tabs-1) * nindent;
- /* otherwise indenting starts at the first level */
- else
- i = tabs * nindent;
-
- /* print leading \t's where possible */
- for ( ; i >= 8; i -= 8)
- fprintf( outfile, "\t");
-
- /* finish up with spaces */
- for ( ; i > 0; i--)
- fprintf( outfile, " ");
-
- } /*--------------------------- ptabs() ----------------------------*/
-
-
- /* getchr() - get character from input file
- *
- * Sets: lastchar to the character gotten from the input file
- *
- * Returns:
- * peek if peek contained a lookahead character
- * getc(inpfile) otherwise
- */
- getchr()
- {
- /* no lookahead char and lastchar not whitespace */
- if (peek < 0 && lastchar != ' ' && lastchar != '\t')
- pchar = lastchar;
-
- /* get the current 'last character' */
- lastchar = (peek < 0) ? getc(inpfile) : peek;
- peek = -1;
-
- return( lastchar == '\r' ? getchr() : lastchar);
-
- } /*------------------------- getchr() ----------------------------*/
-
-
- /* putb() - put the output buffer to the output stream
- *
- */
- putb()
- {
- /* output buffer contains some characters */
- if (j > 0)
- {
- /* we are at the start of a line */
- if (solflg == YES)
- {
- if (addflg == YES) /* we are to add an extra indent */
- {
- if (tabs > 0) /* if things are currently indented */
- tabs++; /* then temporarily add more indent */
- ptabs(); /* and output leading white space */
- tabs--; /* then restore normal indent level */
- addflg = NO; /* and turn the flag off */
- }
- else
- ptabs(); /* output leading white space */
- solflg = NO; /* start-of-line is false now */
- }
- string[j] = '\0'; /* terminate output buffer with null */
- fprintf( outfile, "%s", string); /* write buffer to output stream */
- j = 0; /* mark output buffer as empty now */
- }
-
- /* output buffer is empty */
- else
- {
- if (solflg == YES) /* at start-of-line */
- addflg = NO; /* add-extra-indent is false */
- }
-
- } /*--------------------------- putb() -----------------------------*/
-
-
- /* lookup() - see if string in 'table' is contained in output buffer
- *
- */
- lookup( table)
- char *table[];
- {
- char r;
- int i,kk,k,l;
-
- /* output buffer is empty, can't match that */
- if (j < 1)
- return(NO);
- /* otherwise nul terminate the output buffer */
- else
- string[j] = '\0';
-
- /* skip leading spaces in output buffer */
- kk = 0;
- while (string[kk] == ' ')
- kk++;
-
- /* search the entries in the table until a NULL is found */
- for (i = 0; table[i] != NULL; i++)
- {
- l = 0;
- for( k=kk; (r = table[i][l++]) == string[k] && r != '\0'; k++)
- ;
- if (r == '\0' && (string[k] < 'a' || string[k] > 'z'))
- return( YES); /* match found */
- }
-
- return( NO); /* no match found */
-
- } /*-------------------------- lookup() ---------------------------*/
-
-
- /* cgets() - copy escaped chars and quoted strings to output
- *
- * Returns: last start of sequence character
- */
- cgets()
- {
- char ch; /* char that starts the current sequence */
-
- beg:
- /* copy an escaped character to the output */
- if ((ch = string[j++] = getchr()) == '\\')
- {
- string[j++] = getchr();
- goto beg;
- }
-
- /* character is ' or " */
- if (ch == '\'' || ch == '"')
- {
- /* copy until we hit the terminating ' or " */
- while((cc = string[j++] = getchr()) != ch)
- if (cc == '\\') /* copy escaped characters */
- string[j++] = getchr(); /* unscathed */
- goto beg;
- }
-
- /* if start of char sequence is a newline */
- if (ch == '\n')
- {
- putb(); /* write the output buffer */
- solflg = YES; /* start-of-line is true */
- addflg = YES; /* add-extra-indent is true */
- goto beg; /* and start all over again */
- }
- else
- return( ch); /* otherwise return start of sequence */
-
- } /*-------------------------- cgets() -----------------------------*/
-
-
- /* gotelse() - handle processing after an 'else' is discovered
- *
- * Returns: nothing
- */
- gotelse()
- {
- tabs = stabs[brclev][iflev]; /* return to previous tab level */
- nblk[level] = snblk[brclev][iflev]; /* return to previous nblk level*/
- aflg[level] = saflg[brclev][iflev]; /* return to previous aflg flag */
- ifflg = YES; /* show that we are doing an 'if' stmt */
-
- } /*------------------------- gotelse() ---------------------------*/
-
-
- /* getnl() - get remaining white space and comments
- *
- * Return:
- * 1 YES if we got to a '\n'
- * 0 NO if we did not get to a '\n'
- */
- getnl()
- {
- /* copy white space to output */
- while ((peek = getchr()) == '\t' || peek == ' ')
- {
- string[j++] = peek;
- peek = -1;
- }
- /* we may have a comment to gobble up */
- if ((peek = getchr()) == '/')
- {
- peek = -1; /* don't remember the '/' */
- /* its a comment: copy it to the output */
- if ((peek = getchr()) == '*')
- {
- string[j++] = '/'; /* copy comment start to output */
- string[j++] = '*';
- peek = -1; /* don't remember the peek */
- comment(); /* copy rest of comment to output */
- }
- /* its not a comment: copy the '/' to the output */
- else
- string[j++] = '/';
- }
-
- /* return YES is we have gotten to the newline */
- if ((peek = getchr()) == '\n')
- {
- peek = -1; /* don't remember the peek */
- return( YES);
- }
- return( NO); /* did not find the newline */
-
- } /*--------------------------- getnl() ----------------------------*/
-
-
- /* comment() - copy remainder of a comment to the output
- *
- * Description:
- *
- * At this point the leading '/*' of the comment have been placed
- * into the output buffer. This routine copies the remainder of the
- * comment (even across multiple lines) to the output stream
- *
- * Returns: nothing
- */
-
- comment()
- {
- int temp = tabs; /* temp tabs storage */
- int multiline = NO; /* multiline comment flag */
-
- string[j] = '\0'; /* nul terminate output buffer */
-
- /* process characters inside the comment */
- while ( (c = string[j++] = getchr()) != EOF )
- {
- /* reached the end-of-comment */
- if ( j > 1 && string[j-2] == '*' && c == '/')
- break;
-
- /* hit a newline: flush buffer to output and handle multiline comment */
- if (c == '\n')
- {
- multiline = YES; /* set multiline flag */
- putb(); /* write output buffer */
- string[j] = '\0'; /* nul terminate output string */
- solflg = YES; /* start-of-line is true */
- tabs = 0; /* don't auto-indent next comment lines */
- }
- }
-
- /* doing a multiline comment and last line terminated with newline */
- /* make sure we output the buffer before restoring the normal 'tabs' */
- if (multiline == YES && getnl() == YES)
- {
- string[j++] = '\n'; /* put newline into output buffer */
- putb(); /* and flush buffer to output */
- solflg = YES; /* start-of-line is true */
- }
-
- tabs = temp; /* restore tabs */
-
- } /*-------------------------- comment() ---------------------------*/
-
-
- #ifndef vms
- /*--------------------------------------------------------------------
- * renambak() - rename filename to .BAK
- *
- * Revision History:
- * 08/08/87 Robert B. Sledge Initial Creation.
- *
- * Synopsis:
- * renambak( filename)
- * char *filename; ptr to file to be renamed to .BAK
- *
- * Description:
- * Check that the 'filename' exists, if not then return FAILURE1.
- * A copy of the 'filename' string will have its existing file type
- * stripped and .BAK appended in its place. Then the file will be
- * renamed to .BAK. If this fails due to a previously existing .BAK
- * file then the existing .BAK file will be deleted and the rename
- * will be retried. If this attempt fails then return FAILURE1 for
- * lack of anything more descriptive.
- *
- * Returns:
- * 0 = SUCCESS
- * -1 = FAILURE1: Input File Does Not Exist
- * -2 = FAILURE2: Out of Memory
- *
- * Cautions: Specific to Microsoft C (MS-DOS)
- */
-
- int renambak( filename)
- char *filename; /* ptr to filename string to rename */
- {
- int status = SUCCESS; /* return status */
- char *malloc(); /* memory allocation function */
- char *strchr(); /* character search function */
- char *bakfile; /* ptr to .BAK filename */
- char *p; /* ptr to '.' in filename */
- FILE *stream; /* stream pointer */
-
- /* check that the input file exists */
- if ( (stream=fopen(filename,"r")) == NULL)
- return( FAILURE1);
- fclose( stream); /* close the opened stream */
-
- /* create a temporary copy of the filename */
- if ( (bakfile=malloc(strlen(filename)+6)) == NULL)
- return( FAILURE2);
- strcpy( bakfile, filename); /* copy 'filename' to 'bakfile' */
-
- /* create the .BAK file name string */
- if ( (p=strchr(bakfile,'.')) != NULL) /* ptr to '.' in the string */
- *p = '\0'; /* terminate string at the "." */
- strcat( bakfile, ".BAK"); /* and add .BAK to the end of the string */
-
- /* rename existing file to .BAK */
- if ( rename(filename,bakfile) != SUCCESS)
- { /* another .BAK file is in the way */
- unlink( bakfile); /* try deleting an existing .BAK file */
- if ( rename(filename,bakfile) != SUCCESS)
- status = FAILURE1; /* looks like its just not our day */
- }
-
- free( bakfile); /* free malloc'ed memory */
- return( status); /* and return our status */
-
- } /*--------------------------- renambak() ----------------------------*/
- #endif /* ifndef vms */
-
-
- #ifdef vms
-
- /* findfile.c - return all filespecs that match the wildcard filespec
- *
- * Edit History:
- * 03/02/87 RBS Initial Creation.
- *
- * Synopsis:
- * char *findfile( filespec)
- * char *filespec Pointer to string containing wildcard filespec
- *
- * Description: The file specification (possibly containing wildcards) is
- * passed by pointer "filespec". A pointer to the first matching file
- * specification will be returned. Successive calls to findfile() with the
- * same "filespec" will return successive matching file specs. When no more
- * matching files are found a NULL will be returned. If the "filespec" is
- * changed before all matching files have been returned the routine will
- * start a new file context (effectively erasing the list of remaining files
- * for the previous context).
- *
- * Returns: Pointer to a matching filespec, NULL if no more files match or
- * an error condition occurs.
- *
- * Cautions: This routine is specific to VAX/VMS.
- */
-
- #include <descrip.h> /* for string descriptor definitions */
- #include <ssdef.h> /* defs for system services return values */
- #include <rms.h> /* def for RMS$_NORMAL */
-
- #define MATCH 0 /* strcmp() returns for equal strings */
-
- char *findfile( filespec)
- char *filespec; /* Ptr to string containing wildcard filespec */
- {
- /* local variables */
- struct dsc$descriptor_s ifile; /* input file string descriptor structure */
- struct dsc$descriptor_s rfile; /* result file string descriptor structure */
- static char inpfile[256]; /* storage for the input file specification */
- static struct /* varying string storage structure */
- {
- unsigned short curlen; /* current length of varying string */
- char body[256]; /* body of varying string */
- } vs;
- int status; /* return status from LIB$FIND_FILE */
- static unsigned context=0; /* used by LIB$FIND_FILE to save file context */
-
- /* this is a new input file spec: initialize things */
- if ( strcmp(filespec,inpfile) != MATCH)
- {
- strcpy( inpfile, filespec); /* copy filespec to static string */
- /* there is a current file context: end it since we are starting fresh */
- if (context != 0)
- LIB$FIND_FILE_END( &context); /* end previous context */
- }
-
- /* setup the descriptor for the input (wildcard) filespec string */
- ifile.dsc$w_length = strlen(inpfile); /* string length */
- ifile.dsc$a_pointer = inpfile; /* pointer to string */
- ifile.dsc$b_class = DSC$K_CLASS_S; /* fixed-length descriptor class */
- ifile.dsc$b_dtype = DSC$K_DTYPE_T; /* ASCII string type */
-
- /* setup the descriptor for the output (matching) filespec string */
- rfile.dsc$w_length = 255; /* maximum filename length */
- rfile.dsc$a_pointer = &vs; /* ptr to string structure */
- rfile.dsc$b_class = DSC$K_CLASS_VS; /* varying string class */
- rfile.dsc$b_dtype = DSC$K_DTYPE_VT; /* varying string type */
- vs.curlen = 0; /* no matching string yet */
-
- /* parse the component item from the file specification */
- status = LIB$FIND_FILE( &ifile, &rfile, &context, 0, 0, 0, 0);
- vs.body[vs.curlen] = '\0'; /* null terminate the string */
-
- #ifdef DEBUG
- printf("LIB$FIND = %X, file = %.255s\n", status, vs.body);
- #endif
-
- if (status == RMS$_NORMAL)
- return(vs.body);
- else
- return(NULL);
-
- } /*-------------------------- findfile() -------------------------*/
-
- #endif /* ifdef vms */
-